`include "ascon_define.v"
`define ADDR_W 10
module `ASCON_HASH_CTRL_REGS
(
     input                                       ascon_hash_clk_i,
     input                                       ascon_hash_rst_n_i,
//总线访问信号
     input                                       ascon_hash_ctrl_regs_en_i,
     input                                       ascon_hash_ctrl_regs_wen_i,
     input                     [`CTRL_REG_W-1:0] ascon_hash_ctrl_regs_addr_i,
     input                     [`CTRL_REG_W-1:0] ascon_hash_ctrl_regs_wdata_i,

     output                    [`CTRL_REG_W-1:0] ascon_hash_ctrl_regs_rdata_o,
//状态机访问信号
     input                                       ascon_hash_ctrl_regs_prot_i,  //保护信号，高电平期间，寄存器无法被写
     input                                       ascon_hash_ctrl_regs_fsm_sta_wen_i, //状态机写z状态寄存器写使能信号
     input                                       ascon_hash_ctrl_regs_fsm_en_wen_i, //状态机写使能寄存器写使能信号
     input                     [`CTRL_REG_W-1:0] ascon_hash_ctrl_regs_w_sta_i, //状态寄存器数据
     input                     [`CTRL_REG_W-1:0] ascon_hash_ctrl_regs_w_en_i,  //使能寄存器数据
//输出配置信号
     output                    [`CTRL_REG_W-1:0] ascon_hash_ctrl_regs_msg_block_num_o,
     output                    [`CTRL_REG_W-1:0] ascon_hash_ctrl_regs_msg_addr_o,
     output                    [`CTRL_REG_W-1:0] ascon_hash_ctrl_regs_hash_ctrl_sta_o,
     output                                      ascon_hash_ctrl_regs_hash_ctrl_en_o,
     output                                      ascon_hash_ctrl_regs_hash_ctrl_mode_o,
     output                    [`CTRL_REG_W-1:0] ascon_hash_ctrl_regs_hash_h_addr_o
);
//接口信号
wire                                             reg_en_p;
wire                                             wen_p;
wire                               [`ADDR_W-1:0] addr_p;
wire                           [`CTRL_REG_W-1:0] wdata_p;
reg                            [`CTRL_REG_W-1:0] rdata_p;
wire                                             prot_p;
wire                                             fsm_sta_wen_p;
wire                                             fsm_en_wen_p;
wire                           [`CTRL_REG_W-1:0] w_sta_p;
wire                           [`CTRL_REG_W-1:0] w_en_p;

//寄存器信号
reg                            [`CTRL_REG_W-1:0] msg_block_num;


reg                            [`CTRL_REG_W-1:0] msg_addr;
reg                            [`CTRL_REG_W-1:0] hash_ctrl_sta;
reg                            [`CTRL_REG_W-1:0] hash_ctrl_en;
reg                            [`CTRL_REG_W-1:0] hash_ctrl_mode;
reg                            [`CTRL_REG_W-1:0] hash_h_addr;

wire                                             msg_addr_en;
wire                                             msg_block_num_en;
wire                                             hash_ctrl_sta_en;
wire                                             hash_ctrl_en_en;
wire                                             hash_ctrl_mode_en;
wire                                             hash_h_addr_en;

wire                                             msg_addr_ren;
wire                                             msg_block_num_ren;
wire                                             hash_ctrl_sta_ren;
wire                                             hash_ctrl_en_ren;
wire                                             hash_ctrl_mode_ren;
wire                                             hash_h_addr_ren;

//接口信号连接

assign reg_en_p         = ascon_hash_ctrl_regs_en_i;
assign wen_p            = ascon_hash_ctrl_regs_wen_i;
assign addr_p           = ascon_hash_ctrl_regs_addr_i;
assign wdata_p          = ascon_hash_ctrl_regs_wdata_i;
assign prot_p           = ascon_hash_ctrl_regs_prot_i;
assign fsm_sta_wen_p    = ascon_hash_ctrl_regs_fsm_sta_wen_i;
assign fsm_en_wen_p     = ascon_hash_ctrl_regs_fsm_en_wen_i;
assign w_sta_p          = ascon_hash_ctrl_regs_w_sta_i;
assign w_en_p           = ascon_hash_ctrl_regs_w_en_i;

assign ascon_hash_ctrl_regs_rdata_o         = rdata_p;

assign ascon_hash_ctrl_regs_msg_block_num_o = msg_block_num;
assign ascon_hash_ctrl_regs_msg_addr_o      = msg_addr;
assign ascon_hash_ctrl_regs_hash_ctrl_sta_o = hash_ctrl_sta;
assign ascon_hash_ctrl_regs_hash_ctrl_en_o  = hash_ctrl_en[0];
assign ascon_hash_ctrl_regs_hash_ctrl_mode_o= hash_ctrl_mode[0];
assign ascon_hash_ctrl_regs_hash_h_addr_o   = hash_h_addr;

//内部信号产生
assign msg_block_num_en = (addr_p == `ADDR_W'h00 && reg_en_p == 1'b1 && prot_p == 1'b0) ? 1'b1 : 1'b0;
assign msg_addr_en      = (addr_p == `ADDR_W'h04 && reg_en_p == 1'b1 && prot_p == 1'b0) ? 1'b1 : 1'b0;
assign hash_ctrl_sta_en = (addr_p == `ADDR_W'h08 && reg_en_p == 1'b1 && prot_p == 1'b0) ? 1'b1 : 1'b0;
assign hash_ctrl_en_en  = (addr_p == `ADDR_W'h0c && reg_en_p == 1'b1 && prot_p == 1'b0) ? 1'b1 : 1'b0;
assign hash_ctrl_mode_en= (addr_p == `ADDR_W'h10 && reg_en_p == 1'b1 && prot_p == 1'b0) ? 1'b1 : 1'b0;
assign hash_h_addr_en   = (addr_p == `ADDR_W'h14 && reg_en_p == 1'b1 && prot_p == 1'b0) ? 1'b1 : 1'b0;

assign msg_block_num_ren= (addr_p == `ADDR_W'h00 && reg_en_p == 1'b1) ? 1'b1 : 1'b0;
assign msg_addr_ren     = (addr_p == `ADDR_W'h04 && reg_en_p == 1'b1) ? 1'b1 : 1'b0;
assign hash_ctrl_sta_ren= (addr_p == `ADDR_W'h08 && reg_en_p == 1'b1) ? 1'b1 : 1'b0;
assign hash_ctrl_en_ren = (addr_p == `ADDR_W'h0c && reg_en_p == 1'b1) ? 1'b1 : 1'b0;
assign hash_ctrl_mode_ren= (addr_p == `ADDR_W'h10 && reg_en_p == 1'b1) ? 1'b1 : 1'b0;
assign hash_h_addr_ren  = (addr_p == `ADDR_W'h14 && reg_en_p == 1'b1) ? 1'b1 : 1'b0;

always @(posedge ascon_hash_clk_i or negedge ascon_hash_rst_n_i)
begin : MSG_BLOCK_NUM_PROG
  if (ascon_hash_rst_n_i == 1'b0)
    msg_block_num       <= `CTRL_REG_W'b0;
  else if (msg_block_num_en == 1'b1 && wen_p == 1'b1)
    msg_block_num       <= wdata_p;
  else
    msg_block_num       <= msg_block_num;
end

always @(posedge ascon_hash_clk_i or negedge ascon_hash_rst_n_i)
begin : MSG_ADDR_PROG
  if (ascon_hash_rst_n_i == 1'b0)
    msg_addr            <= `CTRL_REG_W'b0;
  else if (msg_addr_en == 1'b1 && wen_p == 1'b1)
    msg_addr            <= wdata_p;
  else
    msg_addr            <= msg_addr;
end
//状态寄存器：
//[7：0]：状态机状态编号
//[31]  ：算法执行完成标志位
always @(posedge ascon_hash_clk_i or negedge ascon_hash_rst_n_i)
begin : HASH_CTRL_STA_PROG
  if (ascon_hash_rst_n_i == 1'b0)
    hash_ctrl_sta       <= `CTRL_REG_W'b0;
  else if (fsm_sta_wen_p == 1'b1)
    hash_ctrl_sta       <= w_sta_p;
  else if (hash_ctrl_sta_en == 1'b1 && wen_p == 1'b1)
    hash_ctrl_sta       <= wdata_p;
  else
    hash_ctrl_sta       <= hash_ctrl_sta;
end
//算法使能寄存器：
//[0]：1使能 0失能
always @(posedge ascon_hash_clk_i or negedge ascon_hash_rst_n_i)
begin : HASH_CTRL_EN_PROG
  if (ascon_hash_rst_n_i == 1'b0)
    hash_ctrl_en        <= `CTRL_REG_W'b0;
  else if (fsm_en_wen_p == 1'b1)
    hash_ctrl_en        <= w_en_p;
  else if (hash_ctrl_en_en == 1'b1 && wen_p == 1'b1)
    hash_ctrl_en        <= wdata_p;
  else
    hash_ctrl_en        <= hash_ctrl_en;
end

always @(posedge ascon_hash_clk_i or negedge ascon_hash_rst_n_i)
begin : HASH_CTRL_MODE_PROG
  if (ascon_hash_rst_n_i == 1'b0)
    hash_ctrl_mode      <= `CTRL_REG_W'b0;
  else if (hash_ctrl_mode_en == 1'b1 && wen_p == 1'b1)
    hash_ctrl_mode      <= wdata_p;
  else
    hash_ctrl_mode      <= hash_ctrl_mode;
end

always @(posedge ascon_hash_clk_i or negedge ascon_hash_rst_n_i)
begin : HASH_H_ADDR_PROG
  if (ascon_hash_rst_n_i == 1'b0)
    hash_h_addr         <= `CTRL_REG_W'b0;
  else if (hash_h_addr_en == 1'b1 && wen_p == 1'b1)
    hash_h_addr         <= wdata_p;
  else
    hash_h_addr         <= hash_h_addr;
end

always @(*)
begin : RDATA_P_PROG
  if (wen_p == 1'b0)
  begin
    if (msg_addr_en == 1'b1)
      rdata_p           = msg_addr;
    else if (msg_block_num_ren == 1'b1)
      rdata_p           = msg_block_num;
    else if (hash_ctrl_sta_ren == 1'b1)
      rdata_p           = hash_ctrl_sta;
    else if (hash_ctrl_en_ren == 1'b1)
      rdata_p           = hash_ctrl_en;
    else if (hash_ctrl_mode_ren == 1'b1)
      rdata_p           = hash_ctrl_mode;
    else if (hash_h_addr_ren == 1'b1)
      rdata_p           = hash_h_addr;
    else
      rdata_p           = `CTRL_REG_W'b0;
  end
  else
    rdata_p             = `CTRL_REG_W'b0;
end

endmodule